import fs from 'node:fs'
import config from './config.js'

export function watch(callback = ()=>{}, interval = 5000) {
    // 需要忽略的文件
    const ignoreFileList = config?.excude?.file ?? []
    // 需要忽略的文件夹
    const ignoreDirList = config?.excude?.dir ?? []
    // 需要包含的文件 相对项目根路径下的相对路径（例如：./package.json 或 package.json）
    let includeFileList = config?.include ?? []
    
    // 所有路径 包含目录和文件路径
    const all_path = []
    // 文件路径列表
    const filePathList = []
    // 目录路径列表
    const dirPathList = []
    // 已经忽略的文件列表
    const ignoredFileList = []

    // 检查是否存在需要忽略的文件的方法
    function checkFile(file = '', debug = false, fileDebug = false) {
        // 默认 .开头的文件都进行忽略
        let filePathLength = file.split('/').length
        let filename = file.split('/')[filePathLength - 1]
        if (filename.startsWith('.')) {
            ignoredFileList.push(file)
            if (debug || fileDebug) console.log(`\n需要忽略的文件：${ignoreFile}\n已忽略文件路径${file}\n`)
            return false
        }
        for (let ignoreFile of ignoreFileList) {
            // 如果是 .* 则 只需判断当前文件名称是否以 .开头
            if (file.indexOf(ignoreFile) != -1) {
                ignoredFileList.push(file)
                if (debug || fileDebug) console.log(`\n需要忽略的文件：${ignoreFile}\n已忽略文件路径${file}\n`)
                return false
            }
        }
        return true
    }
    // 检查是否存在需要忽略的文件夹的方法
    function checkDir(dir = '', debug = false, dirDebug = false) {
        for (let ignoreDir of ignoreDirList) {
            if (dir.indexOf(ignoreDir) != -1) {
                if (debug || dirDebug) console.log(`\n需要忽略的文件夹：${ignoreDir}\n已忽略文件夹路径${dir}\n`)
                return false
            }
        }
        return true
    }

    // 获取 目录文件列表方法
    function getDirFileList(dir_path, debug = false, fileDebug = false, dirDebug = false) {
        let fileList = null
        //  用于临时存储 每一个文件夹中的当前路径
        let temp_path = ''
        try {
            // 没报错 说明当前path为文件夹
            fileList = fs.readdirSync(dir_path)
            if (temp_path == '') {
                temp_path += `${dir_path}`
            } else {
                temp_path += `/${dir_path}`
            }
            // 当前是文件夹
            if (debug) console.log(`${temp_path == dir_path ? '\n' : '\n\n'}${dir_path}：是文件夹`)
            // 保存符合条件的所有路径 和 目录路径
            if (checkDir(dir_path, debug, dirDebug)) {
                all_path.push(dir_path)
                dirPathList.push(temp_path)
            } else {
                return
            }
        } catch {
            // 报错说明是文件
            if (debug) console.log(`${dir_path}：是文件`)
            // 保存符合条件的所有路径 和 文件路径
            if (checkFile(dir_path, debug, fileDebug)) {
                all_path.push(dir_path)
                filePathList.push(dir_path)
            }
            return
        }
        for (let file of fileList) {
            getDirFileList(temp_path + `/${file}`, debug, fileDebug, dirDebug)
        }
    }

    // 获取需要监听的目录和文件列表
    getDirFileList('.')
    // console.log(dirPathList)
    // 直接监听所有没有忽略的文件 加上额外需要监听的文件
    // 根据配置内容，判断所给路径是否 存在
    // 路径有问题的
    const includeFileErrorList = []
    if(includeFileList.length != 0) {
        // 筛选真实存在的路径
        const ifEixstFile = (path) => {
            try {
                return fs.statSync(path).isFile()
            } catch {
                return false
            }
        }
        includeFileList = includeFileList.filter((path)=>{
            if(ifEixstFile(path)) {
                return true
            } else {
                includeFileErrorList.push(path)
                return false
            }
        })
    }
    if(includeFileErrorList.length != 0) console.warn(`\nconfig.js中配置的 "include" 参数中指定的文件不存在，不存在的有：\n- ${includeFileErrorList.join('\n- ')}\n`)
    console.log(`开始监听项目中 ${filePathList.length + includeFileList.length}个 文件`)
    console.info(`\n- ${filePathList.join('\n- ')}\ninclude参数中的文件有：\n- ${includeFileList.join('\n- ')}\n`)
    filePathList.forEach((filepath) => {
        fs.watchFile(filepath, { interval: interval }, () => {
            callback()
        })
    })
    includeFileList.forEach((path)=>{
        fs.watchFile(path, { interval: interval }, () => {
            callback()
        })
    })
}